﻿#define STORE
#define STOREPRINT
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using Halk.Analyser;
using Halk.Config;
using Halk.Dao;
using Halk.Model;
using Halk.Utils;

namespace Halk.Spider
{
    public class NovelStore : SpiderBase
    {
        private readonly DaoArticle _daoArticle = new DaoArticle(Config.ConfigManage.Instace().GetConfig().ConnString);

        private readonly DaoChapter _daoChapter = new DaoChapter(Config.ConfigManage.Instace().GetConfig().ConnString);

        private readonly DaoAttachs _daoAttachs = new DaoAttachs(Config.ConfigManage.Instace().GetConfig().ConnString);

        private readonly DaoSysMatchs _daoSysMatchs =new DaoSysMatchs(Config.ConfigManage.Instace().GetConfig().ConnString);

        private ArticleInfo _lastInfo = new ArticleInfo();
        
        private static NovelStore _novelStore;

        public static NovelStore Instace()
        {
            return _novelStore ?? (_novelStore = new NovelStore());
        }

        private NovelStore()
        {
            //HasVipChapter = 0;
            if (_daoArticle == null) return;
            Config.AppCache.Instace().MaxArticleId = _daoArticle.GetArticleMaxId();
            Config.AppCache.Instace().MaxChapterId = _daoChapter.GetChapterMaxId();
            Config.AppCache.Instace().MaxAttachId = _daoAttachs.GetAttachMaxID();
        }

        public void StoreNovel(ref AnalyseArticle analyseArticle)
        {
            var article = _daoArticle.GetByName(analyseArticle.Article.articlename);
            var exists = !string.IsNullOrEmpty(article.articlename);
            if (!exists)
            {
                analyseArticle.Article.articleid = Config.AppCache.Instace().MaxArticleId;
                analyseArticle.Article.postdate =TimeHelper.GetDateInt();//int.Parse(DateTime.Now.ToString("MMddHHmmss"));
                analyseArticle.Article.lastupdate = TimeHelper.GetDateInt();//int.Parse(DateTime.Now.ToString("MMddHHmmss"));
                _daoArticle.Add(analyseArticle.Article);
                _lastInfo = analyseArticle.Article;
//#if STOREPRINT
//                if (Config.ConfigManage.Instace().GetConfig().GatherType == "WEB") //WEB
//                {
//                    StoreCover(analyseArticle.Article, analyseArticle.Encode,
//                               Config.ConfigManage.Instace().GetConfig().FilePath);
//                }
//#endif
            }
            else
            {
                analyseArticle.Article = article;
                analyseArticle.Article.lastupdate = TimeHelper.GetDateInt();// int.Parse(DateTime.Now.ToString("yMMddHHmmss"));
            }
        }

        //public void StoreNovel(ref ArticleInfo articleInfo)
        //{
        //    var article = _daoArticle.GetByName(articleInfo.articlename);
        //    var exists = !string.IsNullOrEmpty(article.articlename);
        //    if (!exists)
        //    {
        //        articleInfo.articleid = Config.AppCache.Instace().MaxArticleId;
        //        articleInfo.postdate = TimeHelper.GetDateInt();
        //        articleInfo.lastupdate = TimeHelper.GetDateInt();
        //        _daoArticle.Add(articleInfo);
        //        _lastInfo = articleInfo;
        //    }
        //    else
        //    {
        //        articleInfo = article;
        //        articleInfo.lastupdate = TimeHelper.GetDateInt();// int.Parse(DateTime.Now.ToString("yMMddHHmmss"));
        //    }
        //}

        //public void StoreCover(ArticleInfo article, Encoding encode, string path)
        //{
        //    if (string.IsNullOrEmpty(article.cover)) return;
        //    var cover = HttpHelper.GetImage(article.coverlink, encode);
        //    var link = article.cover;
        //    var coverPath = string.Format(@"{0}\files\article\image\{1}", path, article.articleid/1000);
        //    if (!Directory.Exists(coverPath))
        //        Directory.CreateDirectory(coverPath);

        //    coverPath += string.Format(@"\{0}{1}", article.articleid, link.Substring(link.Length - 4, 4));
        //    cover.Save(coverPath);
        //}

        public bool StoreChapters(string webflag,
            ref AnalyseBookReader analyseBookReader,
             AnalyseChapter analyseChapter)
        {
            var list = GetList(webflag, analyseBookReader.Article);
            if (list.Count == analyseBookReader.BookReader.Count)
            {
                AppCache.Instace().RepeatTimes++;
                return false;
            }
            var lastVolumeId = 0;
            var cindex = 0;
            var begin = 0;
            foreach (var chapterInfo in analyseBookReader.BookReader)
            {
                chapterInfo.articleid = analyseBookReader.Article.articleid;
                chapterInfo.webflag = webflag;
                if (cindex < list.Count) //old
                {
                    begin = cindex;
                    chapterInfo.isnew = chapterInfo.ctype == 1 ? 1 : 0;
                    chapterInfo.volumeid = list[cindex].volumeid; //old volume id
                    chapterInfo.chapterid = list[cindex].chapterid; //old chapter id
                }
                else if (cindex >= list.Count) //new
                {
                    chapterInfo.chapterid = Config.AppCache.Instace().MaxChapterId;
                    if (chapterInfo.chaptertype == 1) //volume
                    {
                        lastVolumeId = analyseBookReader.BookReader[cindex].chapterid;
                    }
                    else if (chapterInfo.chaptertype == 0 && lastVolumeId > 0)
                    {
                        chapterInfo.volumeid = lastVolumeId;
                    }
                    chapterInfo.lastupdate = TimeHelper.GetDateInt();
                    _daoChapter.Add(chapterInfo);
                    if(Config.ConfigManage.Instace().GetConfig().SleepChapter>0)
                    {
                        Thread.Sleep(Config.ConfigManage.Instace().GetConfig().SleepChapter);
                    }
                }
                //?san app最新章节规则
                if (cindex == analyseBookReader.BookReader.Count - 1)
                {
                    analyseBookReader.Article.lastchapterid = chapterInfo.chapterid;
                    analyseBookReader.Article.lastchapter = chapterInfo.chaptername;
                }
                if (chapterInfo.chaptertype != 1 && chapterInfo.isnew != 0)
                {
                    #region set last info
                    _lastInfo.articleid = chapterInfo.articleid;
                    _lastInfo.lastchapterid = chapterInfo.chapterid;
                    _lastInfo.lastchapter = chapterInfo.chaptername;
                    _lastInfo.lastvolumeid = chapterInfo.volumeid;
                    _lastInfo.chapters++;
                    #endregion
                }
                cindex++;
            }
            var tmpList = analyseBookReader.BookReader;
            UpdatePages(ref tmpList, begin-1);
            return true;
        }

    private IList<ChapterInfo> GetList(string webflag, ArticleInfo article)
        {
            if(string.IsNullOrEmpty(webflag))
            {
                return _daoChapter.GetList(article.articleid);
            }
            return _daoChapter.GetList(article.articleid, webflag);
        }

        //public void DownloadTxtReserve(AnalyseBookReader sourceBookReader,
        //    AnalyseBookReader reserveBookReader,
        //    AnalyseChapter analyseChapter,
        //    Dictionary<int, int> relations)
        //{
        //    foreach (ChapterInfo chapter in sourceBookReader.BookReader)
        //    {
        //        //卷,新采集的，VIP章节
        //        if (chapter.chaptertype == 0 && chapter.isnew == 1 && chapter.isvip == 1
        //            && relations.ContainsKey(chapter.chapterid))
        //        {
        //            var items = from s in reserveBookReader.BookReader
        //                        where chapter != null && s.chapterid == chapter.chapterid
        //                        select s;
        //            if(!items.Any())
        //            {
        //                LogManage.Instace().Error(
        //                    string.Format("[10005]Relations find faild.{0}sourcechapterid{1}",
        //                                  reserveBookReader.Rule.RuleID, chapter.chapterid));
        //                continue;
        //            }
        //            GetChapter(analyseChapter,  items.First());
        //        }
        //    }
        //}

        //public void DownloadTxtReserve(IList<ChapterInfo> sourceBookReader,
        //    IList<ChapterInfo> reserveBookReader,
        //    Dictionary<int, int> relations,
        //    string webflag)
        //{
        //    foreach (ChapterInfo chapter in sourceBookReader)
        //    {
        //        //卷,新采集的，VIP章节
        //        if (chapter.chaptertype == 0 
        //            && chapter.isnew == 1
        //            && chapter.isvip == 1
        //            && relations.ContainsKey(chapter.chapterid))
        //        {
        //            var items = from s in reserveBookReader
        //                        where chapter != null && s.chapterid == chapter.chapterid
        //                        select s;
        //            if (!items.Any())
        //            {
        //                LogManage.Instace().Error(string.Format("[10005]Relations find faild.{0}sourcechapterid{1}",
        //                                                        webflag, chapter.chapterid));
        //                continue;
        //            }
        //            GetChapter(items.First());
        //        }
        //    }
        //}

        //public void GetChapter(ChapterInfo chapter)
        //{
        //    var analyseChapter = GetAnalyseChapter(chapter.webflag);

        //    //analyseChapter.SetContent(HttpHelper.Get(chapter.contentslink, analyseChapter.Encode));
        //    //modify by san 由数据库中获取的章节链接
        //    analyseChapter.SetContent(HttpHelper.Get(chapter.chapterlink, analyseChapter.Encode));
        //    if (string.IsNullOrEmpty(analyseChapter.GetContent()))
        //    {
        //        LogManage.Instace().Error("[10002]Content is empty.");
        //        LogManage.Instace().Error(chapter.contentslink);
        //        return;
        //    }
        //    //analyseChapter.SetContent(Utils.HttpHelper.Get("http://www.qidian.com/BookReader/58957,41759098.aspx", analyseChapter.Encode));
        //    var jsTxtLink = "";
        //    var encoding = "";
        //    analyseChapter.AnalyseChapterInfo(chapter, ref jsTxtLink, ref encoding);
        //    if (!string.IsNullOrEmpty(jsTxtLink))
        //    {
        //        analyseChapter.ContentTxt = HttpHelper.Get(jsTxtLink, Encoding.GetEncoding(encoding));
        //        analyseChapter.ClearTxtMark();
        //    }
        //    if (analyseChapter.Attahcs == null || analyseChapter.Attahcs.Count == 0)
        //    {
        //        SaveChapterTxt(chapter, analyseChapter.ContentTxt,
        //                       Config.ConfigManage.Instace().GetConfig().FilePath);
        //        if (chapter.ctype == 1)
        //        {
        //            chapter.ctype = 0;
        //            _daoChapter.Update(chapter);
        //            _daoAttachs.UpdateAttachInvalid(chapter.articleid);
        //        }
        //    }
        //    else
        //    {
        //        chapter.ctype = 1;
        //        _daoChapter.Update(chapter);
        //        foreach (var attach in analyseChapter.Attahcs)
        //        {
        //            DownloadAttach(attach);
        //            _daoAttachs.Add(attach);
        //        }
        //    }
        //}

        //Dictionary<string,AnalyseChapter> _dicAnalyseChapter=new Dictionary<string, AnalyseChapter>(); 

        //public AnalyseChapter GetAnalyseChapter(string webflag)
        //{
        //    if(_dicAnalyseChapter.ContainsKey(webflag))
        //    {
        //        return _dicAnalyseChapter[webflag];
        //    }
        //    else
        //    {
        //        var analyseChapter = new AnalyseChapter();
        //        var rule = RuleManage.Instace().GetRuleFormXml(string.Format("conf/rule/{0}.xml", webflag));
        //        analyseChapter.Rule = rule;
        //        _dicAnalyseChapter[webflag] = analyseChapter;
        //        return analyseChapter;
        //    }
        //}

        //private void SaveChapterTxt(ChapterInfo chapter, string txtContent, string filePath)
        //{
        //    var txtPath = string.Format(@"{0}\files\article\txt\{1}\{2}", filePath, chapter.articleid/1000,
        //                                chapter.articleid);
        //    if (!Directory.Exists(txtPath))
        //        Directory.CreateDirectory(txtPath);

        //    txtPath += @"\" + chapter.chapterid.ToString(CultureInfo.InvariantCulture) + ".txt";
        //    if (!File.Exists(txtPath))
        //    {
        //        using (var sw = new StreamWriter(txtPath, false, Encoding.GetEncoding("utf-8")))
        //        {
        //            sw.Write(txtContent);
        //            sw.Close();
        //        }
        //    }
        //}

        //private void DownloadAttach(AttachInfo attach)
        //{
        //    var link = string.Format("{0}", attach.chapterid.ToString(CultureInfo.InvariantCulture));
        //}

        //只更新qidian内容
        public void CompleteStore()
        {
            _daoArticle.Update(_lastInfo);

        }

        private void UpdatePages(ref IList<ChapterInfo> list, int begin)
        {
            var sql = new StringBuilder();
            if (begin < 0) begin = 0;
            for (int ci = begin; ci < list.Count; ci++)
            {
                if (ci == 0)
                {
                    AnalysePages(ref list, 2, ci);
                }
                else if (ci > 0 && ci < list.Count - 1)
                {
                    AnalysePages(ref list, 1, ci); //有后一章节，且有前一章节
                    AnalysePages(ref list, 2, ci);
                }
                else if (ci == list.Count - 1)
                {
                    AnalysePages(ref list, 1, ci); //有前一章节
                }
                var chapter = list[ci];
                sql.Append("update jieqi_article_chapter set previewpage='" + chapter.previewpage + "',nextpage='" +
                           chapter.nextpage + "' where chapterid='" + chapter.chapterid + "';");

                if (ci > 0 && ci % 1000 == 0)
                {
                    _daoChapter.UpdatePages(sql.ToString());
                    sql.Clear();
                }
            }
            if (sql.Length > 0)
                _daoChapter.UpdatePages(sql.ToString());
        }

        private void AnalysePages(ref IList<ChapterInfo> list, int flag, int posBegin)
        {
            switch (flag)
            {
                case 1://查找上一章节
                    {
                        for (var i = posBegin - 1; i >= 0; i--)
                        {
                            if (list[i].chaptertype != 0) continue;
                            list[posBegin].previewpage = list[i].chapterid;
                            return;
                        }
                    }
                    break;
                case 2://查找下一章节
                    {
                        for (var i = posBegin + 1; i < list.Count; i++)
                        {
                            if (list[i].chaptertype != 0) continue;
                            list[posBegin].nextpage = list[i].chapterid;
                            return;
                        }
                    }
                    break;
            }
        }

        public void SaveBestMatch(ArticleInfo article, string webFlag,bool hasBestBefore)
        {
            if (hasBestBefore)
                _daoSysMatchs.Delete(article.articleid, webFlag);

            var match=new SysMatchsInfo
                          {
                              articleid = article.articleid,
                              webflag = webFlag,
                              automatch = 1,
                              matchdate = Config.AppCache.Instace().GetDateTime()
                          };
            _daoSysMatchs.Add(match);
        }
    }
}
